#include <iostream>
#include <string>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <xapian.h>

using std::cin;
using std::cout;
using std::endl;

char* search(char* subject, char* query) {
  try {
    Xapian::Database db(subject);
    Xapian::Enquire enquire(db);
    Xapian::QueryParser qp;
    Xapian::Stem stemmer("english");

    qp.set_stemmer(stemmer);
    qp.set_database(db);
    qp.set_stemming_strategy(Xapian::QueryParser::STEM_SOME);

    Xapian::Query query_string = qp.parse_query(query);
    enquire.set_query(query_string);

    Xapian::MSet matches = enquire.get_mset(0, 10);
    std::stringstream rank;
    std::stringstream pos;
    std::stringstream weight;
    std::stringstream data;

    int output_length = 0;
    for (Xapian::MSetIterator i = matches.begin(); i != matches.end(); ++i) {
      rank << i.get_rank() + 1;
      weight << i.get_weight();
      pos << *i;
      data << i.get_document().get_data();
      output_length += rank.str().length() + weight.str().length() +
                       pos.str().length() + data.str().length() + 16;

      rank.str("");
      weight.str("");
      pos.str("");
      data.str("");
    }

    char* output = new char[output_length];
    for (Xapian::MSetIterator i = matches.begin(); i != matches.end(); ++i) {
      rank << i.get_rank() + 1;
      weight << i.get_weight();
      pos << *i;
      data << i.get_document().get_data();

      int match_length = rank.str().length() + weight.str().length() +
                         pos.str().length() + data.str().length() + 16;
      char* match_output = new char[match_length];

      strcpy(match_output, rank.str().c_str());
      strcat(match_output, ": ");
      strcat(match_output, weight.str().c_str());
      strcat(match_output, " docid=");
      strcat(match_output, pos.str().c_str());
      strcat(match_output, " [");
      strcat(match_output, data.str().c_str());
      strcat(match_output, "]\n\n");

      if (rank.str() == "1") {
        strcpy(output, match_output);
      } else {
        strcat(output, match_output);
      }

      rank.str("");
      weight.str("");
      pos.str("");
      data.str("");
    }
    return output;
  } catch (Xapian::Error &e) {
    cout << e.get_description() << endl;
    exit(1);
  }
}
/*
int main(int argc, char **argv) {
  cout << search(argv[1], argv[2]);
}
*/
